package com.alipay.sofa.award.biz.service.impl;

import com.alipay.sofa.award.biz.service.enums.AwardEnums;
import com.alipay.sofa.award.biz.service.facade.ActivityAwardFacade;
import com.alipay.sofa.award.biz.service.facade.ActivityTimeFacade;
import com.alipay.sofa.award.common.dal.dao.ActivityTimeMapper;
import com.alipay.sofa.award.common.dal.dataobject.ActivityTime;
import com.alipay.sofa.award.common.dal.dataobject.Award;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;

/**
 * ActivityTimeImpl
 *
 * @author yangguanchao
 * @since 2018/08/27
 */
public class ActivityTimeImpl implements ActivityTimeFacade {

    private static Logger       logger = LoggerFactory.getLogger(ActivityTimeImpl.class);

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private ActivityTimeMapper  activityTimeMapper;

    @Autowired
    private ActivityAwardFacade activityAwardFacade;

    @Override
    public int insertActivityTime(ActivityTime activityTime) {

        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //insert award table because the activity time added
                    for (AwardEnums awardEnums : AwardEnums.values()) {
                        //insert
                        Award award = new Award();
                        //activity time
                        award.setActivityTime(activityTime.getActivityTime());
                        String rank = awardEnums.getRank();
                        award.setRank(rank);
                        award.setTotalCount(awardEnums.getTotalCount());
                        award.setAwardCount(awardEnums.getAwardCount());
                        award.setAwardContent(awardEnums.getAwardContent());
                        award.setAwardDesc(awardEnums.getAwardDesc());
                        //insert or update with the activityTime and rank
                        activityAwardFacade.insertWhenNoExistWithActivityTimeAndRank(award);
                    }
                    //count
                    return activityTimeMapper.insert(activityTime);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("insertActivityTime Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public boolean insertActivityTimeWhenNoExist(ActivityTime activityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<Boolean>() {
            @Override
            public Boolean doInTransaction(TransactionStatus transactionStatus) {
                try {
                    ActivityTime result = activityTimeMapper
                        .selectByUniqueKeyActivityTime(activityTime.getActivityTime());
                    if (result != null) {
                        //no update
                        return false;
                    } else {
                        //insert
                        activityTimeMapper.insert(activityTime);
                        return true;
                    }
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("insertActivityTimeWhenNoExist Error!", exception);
                    return false;
                }
            }
        });
    }

    @Override
    public int deleteById(int id) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return activityTimeMapper.deleteByPrimaryKey(id);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("deleteById Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int deleteByUniqueKeyActivityTime(String activityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //delete award table
                    int count = activityAwardFacade.deleteByActivityTime(activityTime);
                    logger.info("Delete award table activity time is [" + activityTime
                                + "] and count = [" + count + "]");
                    //count
                    return activityTimeMapper.deleteByUniqueKeyActivityTime(activityTime);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("deleteById Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int updateActivityTime(ActivityTime activityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return activityTimeMapper.updateByPrimaryKey(activityTime);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("updateActivityTime Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int updateActivityTime(String oldActivityTime, String updatedActivityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    int activityCount = activityTimeMapper.updateActivityTime(oldActivityTime,
                        updatedActivityTime);
                    int awardCount = activityAwardFacade.updateActivityTime(oldActivityTime,
                        updatedActivityTime);
                    logger.info("Updated activityCount=" + activityCount
                                + " and updated awardCount=" + awardCount + " by oldActivityTime="
                                + oldActivityTime + " and updatedActivityTime="
                                + updatedActivityTime);
                    return awardCount;
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("updateActivityTime Error by oldActivityTime=" + oldActivityTime
                                 + " and updatedActivityTime=" + updatedActivityTime, exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public ActivityTime queryByTime(String activityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<ActivityTime>() {
            @Override
            public ActivityTime doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return activityTimeMapper.selectByUniqueKeyActivityTime(activityTime);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("queryByTime Error!", exception);
                    return null;
                }
            }
        });
    }

    @Override
    public List<ActivityTime> queryAllActivityTime() {
        return this.transactionTemplate.execute(new TransactionCallback<List<ActivityTime>>() {
            @Override
            public List<ActivityTime> doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return activityTimeMapper.selectAllActivityTime();
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("queryAllActivityTime Error!", exception);
                    return null;
                }
            }
        });
    }
}
